#ifndef SUBSDATA_H_
#define SUBSDATA_H_

#define IS_SUBS_INDEX 0 // index of subscription indicator in publishers
#define MIN_CRITICAL_DIST_INDEX 1 // index of critical distance of sensor in publishers
#define MAX_CRITICAL_DIST_INDEX 2 // index of critical distance of sensor in publishers
#define NOT_SUBS 0 // indicates that no one is subscribed for indicated sensor
#define IS_SUBS 1.0 // indicates that someone is subscribed for indicated sensor

#define MESSAGE_BUFFER_LENGTH 32 // maximal message length

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "../utilities/Constants.h"
#include <std_msgs/Float32MultiArray.h>

#include <string>
using namespace std;

/**
 * Sub-Class for the sensors node. This class encapsulates the necessary data for a subscriber: \n
 * - to which topic the sensor information should be published \n
 * - to which sensor(s) the subscriber is subscribed \n
 * - lower and higher bounds of subscribed sensors' values to trigger notification: notifies if values
 *   are smaller than lower bound or greater than higher bound
 */
class SubsData {

public:

	string topic_suffix; // identifies the subsriber while publishing data
	ros::Publisher publishers[sensors_names::NUM_ITEMS]; // publisher for each sensor
	ros::NodeHandle m_node_handler;

	// topic published to each subscriber, informing the relevant sensor
	string sensors_topics[sensors_names::NUM_ITEMS];

	/**

	 0 1 2 3 4 5 6... - sensor number \n
	--------------- \n
	|0|1|0|1|1|0|0| - 1 == has subscription to the sensor \n
	|?|?|?|?|?|?|?| - the min range that subscribers have asked \n
	|?|?|?|?|?|?|?| - the max range that subscribers have asked \n
	--------------- \n
	callback is called if distance is smaller than min or greater than max

	*/
	float sensors_data[3][sensors_names::NUM_ITEMS]; // indicates to which sensor is subscribed

	/**
	 * Constructor- creates a new subscriber
	 * @param topic_suffix suffix to identify the subscriber among other subscribers to the same sensor
	 */
	SubsData(string topic_suffix);

	/**
	 * Subscribes to indicated sensor for requested range of sensor's values
	 * @param sensor_index index of relevant sensor (see \ref ../utilities/Constants.h)
	 * @param min_dist force notifications if sensor's values are smaller than min_dist
	 * @param max_dist force notifications if sensor's values are greater than max_dist
	 * Important examples: \n
	 * -# 	To get notifications only if sensor's value is smaller than 0.7 meters,
	 * 		then min_dist should be 0.7 and max_dist could be 70.0 meters (or any other unreasonably
	 * 		big value)
	 * -#	If subscribing to FRONT_LASER_RANGE, then entire range is published (no filtering).
	 * 		Therefore, min_dist and max_dist are interpreted as start and end indices to indicate
	 * 		relevant section of the range. \n
	 * 		NOTE: possible indices are [0,720]
	 */
	void subscribe(const short& sensor_index, const float& min_dist, const float& max_dist);

	/**
	 * Cancels subscription for indicated sensor
	 * @param sensor_index index of sensor to cancel the subscription for
	 */
	void deSubscribe(const short& sensor_index);

	/**
	 * Checks if subscribed to sensor with given index
	 * @param sensor_index sensor to check
	 * @return True if subscribed, False if not
	 */
	bool isSubscribed(const short& sensor_index) const;

	/**
	 * Checks if subscribe to any sensor
	 * @return True if subscribe to any sensor, False if not
	 */
	bool isSubscribed();

	/**
	 * Updates, in output parameters, the lower and upper bounds for notifications. \n
	 * If subscribed to any sensor but FRONT_LASER_RANGE, the bounds are the sensor's values. \n
	 * If subscribed to FRONT_LASER_RANGE, the bounds are start and end indices of the relevant
	 * section of the range
	 * @param[in] sensor_index index of subscribed sensor
	 * @param[out] min parameter to hold lower bound
	 * @param[out] max parameter to hold upper bound
	 */
	void getRange(const short& sensor_index, float& min, float& max) const;
};

#endif /* SUBSDATA_H_ */
